using System;
using System.Collections;

namespace TrainGame.Model
{
	[Serializable]
	public class TrainCollection : ICollection
	{
		public ArrayList _aTrains;	// JoeB made public for LoadGame serialization

		public Train this [int index]   // indexer declaration
		{ 
			get
			{
				return (Train) _aTrains[index];
			}

			set
			{
				_aTrains[index] = value;
			}
		}

		public void CopyTo(Array a, int index)
		{
			_aTrains.CopyTo(a, index);
		}
		public object SyncRoot
		{
			get{return this;}
		}
		public bool IsSynchronized
		{
			get{return false;}
		}

		public int Count
		{
			get
			{
				return _aTrains.Count;
			}
		}

		public TrainCollection ()
		{
			_aTrains = new ArrayList ();
		}

		public TrainCollection (TrainCollection source)
		{
			_aTrains = (ArrayList)source._aTrains.Clone();
		}


		public void Add (System.Object Train)
		{
			_aTrains.Add (Train);
		}

		public void Add (Train Train)
		{
			_aTrains.Add (Train);
		}

		public void Remove (Train Train)
		{
			_aTrains.Remove (Train);
		}

		public void SortHighestToLowest()
		{
			_aTrains.Sort(new TrainSorter (true));
		}


		// IEnumerable Interface Implementation:
		public IEnumerator GetEnumerator() // non-IEnumerable version
		{
			return _aTrains.GetEnumerator ();
		}

		IEnumerator IEnumerable.GetEnumerator() // IEnumerable version
		{
			//			return (IEnumerator) new ShareEnumerator(this);
			return _aTrains.GetEnumerator ();
		}
	}

	public class TrainSorter : IComparer
	{
		public bool HighestFirst = true;

		public TrainSorter(bool highestFirst)
		{
			HighestFirst = highestFirst;
		}

		#region IComparer Members

		/// <summary>
		/// Compares two trains based on their .Stops member.
		/// This comparer treats Stops less than or equal to 0 to mean a diesel (unlimited stops).
		/// 
		/// This function respects the HighestFirst member variable.
		/// Use it to force highest-first or lowest-first sorting.
		/// </summary>
		/// <param name="x"></param>
		/// <param name="y"></param>
		/// <returns>
		///		-1 for x-before-y
		///		+1 for y-before-x
		///		 0 for x = y
		/// </returns>
		public int Compare(object x, object y)
		{
			Train first = (Train)x;
			Train second = (Train)y;

			return Compare(first, second);
		}

		private int Compare(Train x, Train y)
		{
			if (x.Stops == y.Stops)
				return 0;

			if (HighestFirst)
			{
				// we want the longer train
				if (x.Stops <= 0)
					return -1;	// x is diesel, so it's longer
				if (y.Stops <= 0)
					return +1;	// y is diesel, so it's longer
				if (x.Stops > y.Stops)
					return -1;	// x is longer train
				return +1;		// y is longer train
			}
			else
			{
				// we want the shorter train
				if (x.Stops <= 0)
					return +1;	// x is diesel, so y is shorter
				if (y.Stops <= 0)
					return -1;	// y is diesel, so x is shorter
				if (x.Stops < y.Stops)
					return -1;	// x is shorter train
				return +1;		// y is shorter train
			}
		}

		#endregion
	}

	[Serializable]
	public class Train
	{
		private string		_name;
		private	int			_quantity;
		private int			_cost;
		private	string		_rusts;
		private	int			_tradeUpTo8Cost;
		private	int			_tradeUpToDCost;

		// JoeB - temp so I can compile
		public int Stops = 2;
		public bool UnlimitedStops = false;

		public string Name
		{
			get	{ return _name; }
			set	{ _name = value; }
		}
	
		public int Quantity
		{
			get	{ return _quantity; }
			set	{ _quantity = value; }
		}
	
		public string Rusts
		{
			get	{ return _rusts; }
			set	{ _rusts = value; }
		}
	
		public int Cost
		{
			get	{ return _cost; }
			set	{ _cost = value; }
		}
	
		public int TradeUpTo8Cost
		{
			get	{ return _tradeUpTo8Cost; }
			set	{ _tradeUpTo8Cost = value; }
		}
	
		public int TradeUpToDCost
		{
			get	{ return _tradeUpToDCost; }
			set	{ _tradeUpToDCost = value; }
		}
	

		public Train()
		{
		}
		public Train(string sName, int nQuantity, int nCost, string sRusts, int nTradeTo8Cost, int nTradeToDCost)
		{
			_name				= sName;
			_cost				= nCost;
			_rusts				= sRusts;
			_tradeUpTo8Cost		= nTradeTo8Cost;
			_tradeUpToDCost		= nTradeToDCost;
		}
	}
}
